﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using System.ComponentModel;
using DevExpress.XtraBars;
using ProgNetComponents.Utils;
using ProgNetComponentsDx.Shortcut.Design;

namespace ProgNetComponentsDx.Shortcut
{
    [Designer(typeof(ShortcutProviderDesigner))]
    public class ShortcutProvider : Base.Components.BaseExtenderProvider<ShortcutSettings>
    {
        public ShortcutProvider()
            : base()
        {
            Initialize();
        }
        public ShortcutProvider(IContainer container)
            : base(container)
        {
            Initialize();
        }

        private ToolTip toolTip = new ToolTip();
        private DefaultBool _AlwaysDisplayToolTips = DefaultBool.Default;
        private DefaultBool _AlwaysAllowEdit = DefaultBool.Default;
        private DefaultBool _AlwaysAddShortcutToText = DefaultBool.Default;

        private void Initialize()
        {
            AlwaysDisplayToolTips = DefaultBool.Default;
            AlwaysAllowEdit = DefaultBool.Default;
            if (!this.IsDesignMode())
            {
                ShortcutCache.ShortcutChanged += new EventHandler<ShortcutEventArgs>(ShortcutCache_ShortcutChanged);
                Language.ProgNetLanguage.LanguageChanged += new EventHandler(ProgNetLanguage_LanguageChanged);
            }
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                ShortcutCache.ShortcutChanged -= new EventHandler<ShortcutEventArgs>(ShortcutCache_ShortcutChanged);
                Language.ProgNetLanguage.LanguageChanged -= new EventHandler(ProgNetLanguage_LanguageChanged);
            }
            base.Dispose(disposing);
        }
        public int AutoPopDelay
        {
            get { return toolTip.AutoPopDelay; }
            set { toolTip.AutoPopDelay = value; }
        }

        public int AutomaticDelay
        {
            get { return toolTip.AutomaticDelay; }
            set { toolTip.AutomaticDelay = value; }
        }

        public int InitialDelay
        {
            get { return toolTip.InitialDelay; }
            set { toolTip.InitialDelay = value; }
        }

        public DefaultBool AlwaysDisplayToolTips
        {
            get { return _AlwaysDisplayToolTips; }
            set
            {
                _AlwaysDisplayToolTips = value;
                PrepareTooltip();
            }
        }

        public DefaultBool AlwaysAllowEdit
        {
            get { return _AlwaysAllowEdit; }
            set
            {
                _AlwaysAllowEdit = value;
            }
        }
        public DefaultBool AlwaysAddShortcutToText
        {
            get { return _AlwaysAddShortcutToText; }
            set
            {
                _AlwaysAddShortcutToText = value;
            }
        }

        void ProgNetLanguage_LanguageChanged(object sender, EventArgs e)
        {
            foreach (KeyValuePair<object , ShortcutSettings> kvp in AllObjects)
            {
                if (kvp.Value.AddShortCutToText)
                {
                    PrepareName(kvp.Key, kvp.Value);
                }
            }
        }

        ~ShortcutProvider()
        {
            ShortcutCache.ShortcutChanged -= new EventHandler<ShortcutEventArgs>(ShortcutCache_ShortcutChanged);
            Language.ProgNetLanguage.LanguageChanged -= new EventHandler(ProgNetLanguage_LanguageChanged);
        }

        void ShortcutCache_ShortcutChanged(object sender, ShortcutEventArgs e)
        {
            foreach (KeyValuePair<object , ShortcutSettings> kvp in AllObjects)
            {
                if (ShortcutCache.IsTheSameId(e.ShortcutId, kvp.Value.RealShortCutId))
                {
                    ProcessObject(kvp.Key, kvp.Value);
                }
            }
        }
        
        private Form form = null;

        #region menu
        private System.ComponentModel.IContainer components = null;
        private DevExpress.XtraBars.BarManager barManager1;
        private DevExpress.XtraBars.PopupMenu popupMenu1;
        private DevExpress.XtraBars.BarButtonItem bbiShortcut;
        #endregion
        #region menu Initialize
        private void SchowMenu(object target)
        {
            if (barManager1 == null)
                InitializeMenu();
            bbiShortcut.Tag = target;
            popupMenu1.ShowPopup(Control.MousePosition);
        }
        private void InitializeMenu()
        {
            this.components = new System.ComponentModel.Container();
            this.barManager1 = new DevExpress.XtraBars.BarManager(components);
            barManager1.Form = form;
            this.popupMenu1 = new DevExpress.XtraBars.PopupMenu(components);
            this.bbiShortcut = new DevExpress.XtraBars.BarButtonItem();
            ((System.ComponentModel.ISupportInitialize)(this.barManager1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).BeginInit();
            // 
            // barManager1
            // 
            this.barManager1.Items.AddRange(new DevExpress.XtraBars.BarItem[] {
            this.bbiShortcut});
            this.barManager1.MaxItemId = 1;
            // 
            // popupMenu1
            // 
            this.popupMenu1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] {
            new DevExpress.XtraBars.LinkPersistInfo(this.bbiShortcut)});
            this.popupMenu1.Manager = this.barManager1;
            this.popupMenu1.Name = "popupMenu1";
            // 
            // bbiShortcut
            // 
            this.bbiShortcut.Caption = "Skrót Klawiszowy";
            this.bbiShortcut.Id = 0;
            this.bbiShortcut.Name = "bbiShortcut";
            this.bbiShortcut.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(bbiShortcut_ItemClick);
            ((System.ComponentModel.ISupportInitialize)(this.barManager1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).EndInit();

        }

        #endregion

        void bbiShortcut_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            ShortcutSettings settings = GetSettings(e.Item.Tag);
            if (settings.IsShortcutIdSet)
            {
                using (FormShortCutForUser f = new FormShortCutForUser())
                {
                    object shId = null;
                    f.Keys = GetShortcutKeys(settings);
                    shId = settings.RealShortCutId;

                    if (f.ShowDialog() == DialogResult.OK)
                    {
                        ShortcutCache.SetShortcut(shId, f.ShortcutValue.Key, true);
                    }
                }
            }
        }
        private Keys GetShortcutKeys(ShortcutSettings settings)
        {
            Keys k;
            if (settings.IsCustomShortcut)
            {
                if (ShortcutCache.IsShortcutSaved(settings.CustomShortcutId))
                    k = ShortcutCache.GetShortkutKeys(settings.CustomShortcutId);
                else
                    k = settings.CustomDefaultShortcut;
            }
            else
            {
                k = ShortcutCache.GetShortkutKeys(settings.ShortCutId);
            }
            return k;
        }
        private void PrepareName(object target, ShortcutSettings settings)
        {
            string newShortcutText = "";
            Keys k = GetShortcutKeys(settings);

            if (k != Keys.None)
                newShortcutText = k.AsString();
            else
                newShortcutText = "";
            if (target is Control)
            {
                string text = ((Control)(target)).Text;
                if (settings.ShortcutText.IsNotNull() && text.EndsWith(" (" + settings.ShortcutText + ")"))
                {
                    text = text.SubstringSafe(0, text.Length - settings.ShortcutText.Length - 3);
                }
                if (AlwaysAddShortcutToText.AsBool(settings.AddShortCutToText))
                {
                    if (newShortcutText.IsNotNull())
                        text = text + " (" + newShortcutText + ")";
                }
                ((Control)(target)).Text = text;
                settings.ShortcutText = newShortcutText;
            }
        }

        protected override void ProcessObject(object target, ShortcutSettings settings)
        {
            if (!this.IsDesignMode())
            {
                PrepareForm(target);
                
                if (target is Control)
                {
                    PrepareName(target, settings);
                    PrepareTooltip(target, settings);
                    
                    ((Control)(target)).MouseDown -= new MouseEventHandler(ShortcutProvider_MouseDown);
                    ((Control)(target)).MouseDown += new MouseEventHandler(ShortcutProvider_MouseDown);
                }
                
            }
        }
        protected void PrepareTooltip()
        {
            foreach (var kvp in AllObjects)
                PrepareTooltip(kvp.Key, kvp.Value);
        }
        protected void PrepareTooltip(object target, ShortcutSettings settings)
        {
            if (!this.IsDesignMode())
            {
                if (target is Control)
                {
                    if (AlwaysDisplayToolTips.AsBool(settings.DisplayTooltip))
                    {
                        toolTip.SetToolTip((Control)(target), settings.ShortcutText);
                    }
                    else
                    {
                        toolTip.SetToolTip((Control)(target), string.Empty);
                    }
                }
            }
        }
        void ShortcutProvider_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                ShortcutSettings settings = GetSettings(sender);
                if (settings != null && (AlwaysAllowEdit.AsBool(settings.AllowEdit)))
                {
                    SchowMenu(sender);
                }
            }
        }

        private void PrepareForm(object target)
        {
            if (form == null && !this.IsDesignMode())
            {
                if (target is Control)
                {
                    form = ((Control)(target)).FindForm();
                }
                else
                {
                    form = Form.ActiveForm;
                }
                if (form != null)
                {
                    form.KeyPreview = true;
                    form.KeyDown += new KeyEventHandler(form_KeyDown);
                }
            }
        }

        void form_KeyDown(object sender, KeyEventArgs e)
        {
            foreach (KeyValuePair<object, ShortcutSettings> kvp in this.AllObjects)
            {
                if (kvp.Value.IsShortcutIdSet)
                {
                    Keys k = GetShortcutKeys(kvp.Value);
                    if (k != Keys.None && k == e.KeyData)
                    {
                        if (kvp.Key is SimpleButton)
                        {
                            ((SimpleButton)(kvp.Key)).PerformClick();
                            e.Handled = true;
                        }
                        else if (kvp.Key is Button)
                        {
                            ((Button)(kvp.Key)).PerformClick();
                            e.Handled = true;
                        }
                    }
                }
            }
        }

        protected override ShortcutSettings CreateSettings(object target)
        {
            return new ShortcutSettings(target, this);
        }

        public override bool CanExtend(object extendee)
        {
            if (extendee is Button ||
                extendee is SimpleButton)
                return true;
            //if ((extendee is BarItem) && !(extendee is BarSubItem))
            //    return true;
            return false;
        }
    }
}
